// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 

package com.imsl.finance;

import java.text.DateFormat;
import java.text.Format;
import java.util.GregorianCalendar;

import com.imsl.Messages;
import com.imsl.math.ZeroFunction;

// Referenced classes of package com.imsl.finance:
//            DayCountBasis, BasisPart

public class Bond
{
    public static final int ANNUAL = 1;
    public static final int SEMIANNUAL = 2;
    public static final int QUARTERLY = 4;
    private static Format format = DateFormat.getDateInstance(1);

    public static double accrint(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, GregorianCalendar gregoriancalendar2, double d, double d1, int i, 
            DayCountBasis daycountbasis)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "rate", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d1 <= 0.0D)
        {
            Object aobj1[] = {
                "par", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj1);
        }
        if(!gregoriancalendar.before(gregoriancalendar2))
        {
            Object aobj2[] = {
                "issue", gregoriancalendar, "settlement", gregoriancalendar2
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.NotBefore", aobj2);
        }
        int j = monthsFromFrequency(i);
        double d2 = 0.0D;
        GregorianCalendar gregoriancalendar3 = (GregorianCalendar)gregoriancalendar1.clone();
        GregorianCalendar gregoriancalendar4 = (GregorianCalendar)gregoriancalendar1.clone();
        gregoriancalendar4.add(2, -j);
        for(; gregoriancalendar3.after(gregoriancalendar); gregoriancalendar3.add(2, -j))
        {
            GregorianCalendar gregoriancalendar5 = gregoriancalendar4;
            GregorianCalendar gregoriancalendar6 = gregoriancalendar3;
            if(gregoriancalendar.after(gregoriancalendar5))
                gregoriancalendar5 = gregoriancalendar;
            if(gregoriancalendar2.before(gregoriancalendar6))
                gregoriancalendar6 = gregoriancalendar2;
            double d3 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar5, gregoriancalendar6);
            if(d3 > 0.0D)
            {
                double d4 = daycountbasis.getYearBasis().daysInPeriod(gregoriancalendar3, i);
                d2 += d3 / d4;
            }
            gregoriancalendar4.add(2, -j);
        }

        return d1 * (d / (double)i) * d2;
    }

    public static double accrintm(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, DayCountBasis daycountbasis)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "rate", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d1 <= 0.0D)
        {
            Object aobj1[] = {
                "par", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj1);
        }
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj2[] = {
                "issue", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj2);
        }
        double d2 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        double d3 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        return d1 * d * (d2 / d3);
    }

    public static double amordegrc(double d, GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d1, int i, double d2, DayCountBasis daycountbasis)
    {
        int j = 1;
        double d3 = (0.0D / 0.0D);
        if(d2 <= 0.0D)
        {
            Object aobj[] = {
                "rate", new Double(d2)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d2 >= 0.5D)
        {
            Object aobj1[] = {
                "rate", new Double(d2), new Double(0.5D)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "TooBig", aobj1);
        }
        if(d <= 0.0D)
        {
            Object aobj2[] = {
                "cost", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj2);
        }
        if(d1 < 0.0D)
        {
            Object aobj3[] = {
                "salvage", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj3);
        }
        if((double)i < 0.0D)
        {
            Object aobj4[] = {
                "period", new Double(i)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj4);
        }
        if(!gregoriancalendar1.after(gregoriancalendar))
        {
            Object aobj5[] = {
                "firstPeriod", gregoriancalendar1, "issue", gregoriancalendar
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.NotAfter", aobj5);
        }
        if((double)i < 0.0D)
        {
            Object aobj6[] = {
                "period", new Double(i)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj6);
        }
        double d4 = 1.0D / d2;
        double d5 = 0.0D;
        if(d4 >= 6D)
            d5 = 2.5D;
        else
        if(d4 >= 5D)
            d5 = 2D;
        else
            d5 = 1.5D;
        double d6 = d4 - Math.floor(d4);
        if(d6 == 0.0D)
            d4 = d4;
        else
            d4 = Math.floor(d4) + 1.0D;
        d4 = Math.rint(d4);
        double d7 = coupdaysnc(gregoriancalendar, gregoriancalendar1, j, daycountbasis);
        double d8 = coupdaysMonthly(gregoriancalendar, gregoriancalendar1, j, daycountbasis);
        int k = coupnum(gregoriancalendar, gregoriancalendar1, j, daycountbasis);
        if(k <= 1)
        {
            d7 /= d8;
        } else
        {
            int l = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
            d7 = (double)l / d8;
        }
        double d9 = d * d7 * d2 * d5;
        if(d9 > d - d1)
            d9 = d - d1;
        double d10 = d9 - Math.rint(d9);
        d9 = Math.rint(d9);
        double d13 = d10;
        double d14 = 0.0D;
        if(i < 1)
            d3 = d9;
        else
        if((double)i < d4 - 2D)
        {
            double d15 = d - d9;
            int i1 = 0;
            do
            {
                if(i1 >= i)
                    break;
                d3 = d15 * d2 * d5;
                double d11 = d3 - Math.rint(d3);
                d3 = Math.rint(d3);
                d13 += d11;
                if(d15 < d1)
                {
                    d3 = 0.0D;
                    break;
                }
                d15 -= d3;
                i1++;
            } while(true);
        } else
        if((double)i == d4 - 2D || (double)i == d4 - 1.0D)
        {
            double d16 = d - d9;
            int j1 = 0;
            do
            {
                if((double)j1 >= d4 - 3D)
                    break;
                d3 = d16 * d2 * d5;
                double d12 = d3 - Math.rint(d3);
                d3 = Math.rint(d3);
                d13 += d12;
                if(d16 < d1)
                {
                    d3 = 0.0D;
                    break;
                }
                d16 -= d3;
                j1++;
            } while(true);
            if(d16 < d1)
            {
                d3 = 0.0D;
            } else
            {
                d3 = (d16 - d13) * 0.5D;
                d3 = Math.rint(d3);
            }
        } else
        {
            d3 = 0.0D;
        }
        return d3;
    }

    public static double amorlinc(double d, GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d1, int i, double d2, DayCountBasis daycountbasis)
    {
        int j = 1;
        double d3 = (0.0D / 0.0D);
        if(d2 <= 0.0D)
        {
            Object aobj[] = {
                "rate", new Double(d2)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d <= 0.0D)
        {
            Object aobj1[] = {
                "cost", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj1);
        }
        if(d1 < 0.0D)
        {
            Object aobj2[] = {
                "salvage", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj2);
        }
        if((double)i < 0.0D)
        {
            Object aobj3[] = {
                "period", new Double(i)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj3);
        }
        if(!gregoriancalendar1.after(gregoriancalendar))
        {
            Object aobj4[] = {
                "firstPeriod", gregoriancalendar1, "issue", gregoriancalendar
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.NotAfter", aobj4);
        }
        double d4 = 1.0D / d2;
        double d5 = d4 - Math.floor(d4);
        if(d5 != 0.0D)
            d4 = Math.floor(d4) + 1.0D;
        d4 = Math.floor(d4);
        double d6 = coupdaysnc(gregoriancalendar, gregoriancalendar1, j, daycountbasis);
        double d7 = coupdaysMonthly(gregoriancalendar, gregoriancalendar1, j, daycountbasis);
        int k = coupnum(gregoriancalendar, gregoriancalendar1, j, daycountbasis);
        if(k <= 1)
        {
            d6 /= d7;
        } else
        {
            int l = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
            d6 = (double)l / d7;
        }
        double d8 = d * d6 * d2;
        if(d8 > d - d1)
            d8 = d - d1;
        double d9 = 0.0D;
        double d12 = d * d2;
        if(i < 1)
            d3 = d8;
        else
        if((double)i < d4)
        {
            double d10 = d - d8;
            int i1 = 0;
            do
            {
                if(i1 >= i)
                    break;
                d3 = d12;
                if(d10 < d1 + d12)
                {
                    if(i1 == i - 1)
                        d3 = d10 - d1;
                    else
                        d3 = 0.0D;
                    break;
                }
                d10 -= d3;
                i1++;
            } while(true);
        } else
        if((double)i == d4)
        {
            double d11 = d - d8;
            int j1 = 0;
            do
            {
                if((double)j1 >= d4 - 1.0D)
                    break;
                d3 = d12;
                if(d11 < d1 + d12)
                {
                    d3 = d11 - d1;
                    d11 -= d3;
                    break;
                }
                d11 -= d3;
                j1++;
            } while(true);
            if(d11 < d1)
                d3 = 0.0D;
            else
                d3 = d11 - d1;
        } else
        {
            d3 = 0.0D;
        }
        return d3;
    }

    public static double coupdays(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, int i, DayCountBasis daycountbasis)
    {
        return coupdays(gregoriancalendar, gregoriancalendar1, i, daycountbasis.getYearBasis());
    }

    private static double coupdaysMonthly(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, int i, DayCountBasis daycountbasis)
    {
        return coupdays(gregoriancalendar, gregoriancalendar1, i, daycountbasis.getMonthBasis());
    }

    private static double coupdays(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, int i, BasisPart basispart)
    {
        int j = monthsFromFrequency(i);
        GregorianCalendar gregoriancalendar2 = (GregorianCalendar)gregoriancalendar1.clone();
        gregoriancalendar2.add(2, -j);
        GregorianCalendar gregoriancalendar3 = (GregorianCalendar)gregoriancalendar1.clone();
        for(; gregoriancalendar2.after(gregoriancalendar); gregoriancalendar3.add(2, -j))
            gregoriancalendar2.add(2, -j);

        return basispart.daysInPeriod(gregoriancalendar3, i);
    }

    public static int coupdaybs(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, int i, DayCountBasis daycountbasis)
    {
        GregorianCalendar gregoriancalendar2 = couppcd(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        return daycountbasis.getMonthBasis().daysBetween(gregoriancalendar2, gregoriancalendar);
    }

    public static int coupdaysnc(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, int i, DayCountBasis daycountbasis)
    {
        GregorianCalendar gregoriancalendar2 = coupncd(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        return daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar2);
    }

    public static GregorianCalendar couppcd(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, int i, DayCountBasis daycountbasis)
    {
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj);
        }
        int j = monthsFromFrequency(i);
        GregorianCalendar gregoriancalendar2;
        for(gregoriancalendar2 = (GregorianCalendar)gregoriancalendar1.clone(); gregoriancalendar2.after(gregoriancalendar); gregoriancalendar2.add(2, -j));
        return gregoriancalendar2;
    }

    public static GregorianCalendar coupncd(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, int i, DayCountBasis daycountbasis)
    {
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj);
        }
        int j = monthsFromFrequency(i);
        GregorianCalendar gregoriancalendar2;
        for(gregoriancalendar2 = (GregorianCalendar)gregoriancalendar1.clone(); gregoriancalendar2.after(gregoriancalendar); gregoriancalendar2.add(2, -j));
        gregoriancalendar2.add(2, j);
        return gregoriancalendar2;
    }

    public static int coupnum(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, int i, DayCountBasis daycountbasis)
    {
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj);
        }
        int j = monthsFromFrequency(i);
        int k = 0;
        for(GregorianCalendar gregoriancalendar2 = (GregorianCalendar)gregoriancalendar.clone(); gregoriancalendar2.before(gregoriancalendar1);)
        {
            gregoriancalendar2.add(2, j);
            k++;
        }

        return k;
    }

    public static double disc(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, DayCountBasis daycountbasis)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "price", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d1 <= 0.0D)
        {
            Object aobj1[] = {
                "redemption", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj1);
        }
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj2[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj2);
        }
        double d2 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        double d3 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        return ((d1 - d) * d2) / (d1 * d3);
    }

    public static double duration(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, int i, DayCountBasis daycountbasis)
    {
        if(d < 0.0D)
        {
            Object aobj[] = {
                "coupon", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj);
        }
        if(d1 < 0.0D)
        {
            Object aobj1[] = {
                "yield", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj1);
        }
        if(!gregoriancalendar.before(gregoriancalendar1))
        {
            Object aobj2[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.NotBefore", aobj2);
        }
        double d2 = coupdaysnc(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        double d3 = coupdaysMonthly(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        int j = coupnum(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        double d4 = 1.0D + d1 / (double)i;
        double d5 = ((double)j - 1.0D) + d2 / d3;
        double d6 = 1.0D - d2 / d3;
        double d7 = 0.0D;
        double d8 = 0.0D;
        d *= 100 / i;
        double d9 = 1.0D / Math.pow(d4, d6);
        for(int k = 1; k <= j; k++)
        {
            d9 /= d4;
            d7 += d * ((double)k - d6) * d9;
            d8 += d * d9;
        }

        double d10 = Math.pow(d4, d5);
        double d11 = (d5 * 100D) / d10 + d7;
        double d12 = (100D / d10 + d8) * (double)i;
        return d11 / d12;
    }

    public static double convexity(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, int i, DayCountBasis daycountbasis)
    {
        if(d < 0.0D)
        {
            Object aobj[] = {
                "coupon", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj);
        }
        if(d1 < 0.0D)
        {
            Object aobj1[] = {
                "yield", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj1);
        }
        if(!gregoriancalendar.before(gregoriancalendar1))
        {
            Object aobj2[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.NotBefore", aobj2);
        }
        double d2 = coupdaysnc(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        double d3 = coupdaysMonthly(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        int j = coupnum(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        double d4 = 1.0D + d1 / (double)i;
        double d5 = 1.0D - d2 / d3;
        d /= i;
        double d6 = 0.0D;
        double d7 = 0.0D;
        double d8 = 0.0D;
        double d9 = 0.0D;
        for(int k = 1; k <= j; k++)
        {
            d9 = (double)k - d5;
            d8 = 1.0D / Math.pow(d4, d9);
            d6 += d9 * (d9 + 1.0D) * d * d8;
            d7 += d * d8;
        }

        d6 += d9 * (d9 + 1.0D) * d8;
        d7 += d8;
        return d6 / d7 / (d4 * d4 * (double)i * (double)i);
    }

    public static double intrate(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, DayCountBasis daycountbasis)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "investment", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d1 <= 0.0D)
        {
            Object aobj1[] = {
                "redemption", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj1);
        }
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj2[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj2);
        }
        double d2 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        double d3 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        return ((d1 - d) / d) * (d2 / d3);
    }

    public static double mduration(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, int i, DayCountBasis daycountbasis)
    {
        double d2 = 1.0D + d1 / (double)i;
        return duration(gregoriancalendar, gregoriancalendar1, d, d1, i, daycountbasis) / d2;
    }

    public static double price(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, double d2, 
            int i, DayCountBasis daycountbasis)
    {
        if(d < 0.0D)
        {
            Object aobj[] = {
                "rate", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj);
        }
        if(d1 < 0.0D)
        {
            Object aobj1[] = {
                "yield", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj1);
        }
        if(!gregoriancalendar1.after(gregoriancalendar))
        {
            Object aobj2[] = {
                "maturity", gregoriancalendar1, "settlement", gregoriancalendar
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.NotAfter", aobj2);
        }
        int j = coupdaybs(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        double d3 = coupdays(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        double d4 = d3 - (double)j;
        int k = coupnum(gregoriancalendar, gregoriancalendar1, i, daycountbasis);
        double d5 = 1.0D + d1 / (double)i;
        double d6 = Math.pow(d5, d4 / d3);
        double d7 = d2 / (d6 * Math.pow(d5, k - 1));
        double d8 = 0.0D;
        double d9 = 1.0D / d6;
        for(int l = 1; l <= k; l++)
        {
            d8 += d9;
            d9 /= d5;
        }

        double d10 = (double)j / d3;
        return d7 + 100D * (d / (double)i) * (d8 - d10);
    }

    public static double pricedisc(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, DayCountBasis daycountbasis)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "rate", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d1 <= 0.0D)
        {
            Object aobj1[] = {
                "redemption", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj1);
        }
        double d2 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        double d3 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        return d1 - (d * d1 * d3) / d2;
    }

    public static double priceyield(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, DayCountBasis daycountbasis)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "yield", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d1 <= 0.0D)
        {
            Object aobj1[] = {
                "redemption", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj1);
        }
        double d2 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        double d3 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        return d1 / (1.0D + d * (d3 / d2));
    }

    public static double pricemat(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, GregorianCalendar gregoriancalendar2, double d, double d1, DayCountBasis daycountbasis)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "rate", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d1 < 0.0D)
        {
            Object aobj1[] = {
                "yield", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj1);
        }
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj2[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj2);
        }
        double d2 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar2, gregoriancalendar);
        double d3 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar2, gregoriancalendar1);
        double d4 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        double d5 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        double d6 = (d2 / d5) * d;
        double d7 = 1.0D + (d3 * d) / d5;
        double d8 = 1.0D + (d4 * d1) / d5;
        return 100D * (d7 / d8 - (d2 * d) / d5);
    }

    public static double received(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, DayCountBasis daycountbasis)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "investment", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(d1 <= 0.0D)
        {
            Object aobj1[] = {
                "rate", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj1);
        }
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj2[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj2);
        }
        double d2 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        double d3 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        return d / (1.0D - (d1 * d2) / d3);
    }

    public static double tbilleq(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "rate", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj1[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj1);
        }
        int i = DayCountBasis.BasisPartActual.daysBetween(gregoriancalendar, gregoriancalendar1);
        if(i > 366)
        {
            Object aobj2[] = {
                gregoriancalendar1, gregoriancalendar
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.OverYear", aobj2);
        }
        if(i <= 182)
        {
            return (365D * d) / (360D - d * (double)i);
        } else
        {
            double d1 = (double)Math.min(365, i) / 365D;
            double d2 = d1 * d1 - (2D * d1 - 1.0D) * ((d * (double)i) / (d * (double)i - 360D));
            return (-d1 + Math.sqrt(d2)) / (d1 - 0.5D);
        }
    }

    public static double tbillprice(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "rate", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj1[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj1);
        }
        int i = DayCountBasis.BasisPartActual.daysBetween(gregoriancalendar, gregoriancalendar1);
        return 100D * (1.0D - (d * (double)i) / 360D);
    }

    public static double tbillyield(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d)
    {
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj);
        }
        int i = DayCountBasis.BasisPartActual.daysBetween(gregoriancalendar, gregoriancalendar1);
        if(i > 366)
        {
            Object aobj1[] = {
                gregoriancalendar1, gregoriancalendar
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.OverYear", aobj1);
        }
        return ((100D - d) / d) * (360D / (double)i);
    }

    public static double yielddisc(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, double d, double d1, DayCountBasis daycountbasis)
    {
        if(d <= 0.0D)
        {
            Object aobj[] = {
                "price", new Double(d)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj1[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj1);
        }
        double d2 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        double d3 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        return ((d1 - d) / d) * (d2 / d3);
    }

    public static double yield(final GregorianCalendar settlement, final GregorianCalendar maturity, final double rate, final double price, final double redemption, 
            final int frequency, final DayCountBasis basis)
    {
        if(price <= 0.0D)
        {
            Object aobj[] = {
                "price", new Double(price)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(rate < 0.0D)
        {
            Object aobj1[] = {
                "rate", new Double(rate)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Negative", aobj1);
        }
        if(settlement.after(maturity))
        {
            Object aobj2[] = {
                "settlement", settlement, "maturity", maturity
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj2);
        }
        com.imsl.math.ZeroFunction.Function function = new com.imsl.math.ZeroFunction.Function() {

            public double f(double d1)
            {
                if(d1 <= 0.0D)
                    return -10D * d1 * price;
                else
                    return price - Bond.price(settlement, maturity, rate, d1, redemption, frequency, basis);
            }

        }
;
        double d = 9.9999999999999998E-013D;
        ZeroFunction zerofunction = new ZeroFunction();
        zerofunction.setAbsoluteError(d);
        zerofunction.setRelativeError(d);
        double ad[] = {
            0.10000000000000001D
        };
        double ad1[] = zerofunction.computeZeros(function, ad);
        return ad1[0];
    }

    public static double yieldmat(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, GregorianCalendar gregoriancalendar2, double d, double d1, DayCountBasis daycountbasis)
    {
        if(d1 <= 0.0D)
        {
            Object aobj[] = {
                "price", new Double(d1)
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "NotPositive", aobj);
        }
        if(gregoriancalendar.after(gregoriancalendar1))
        {
            Object aobj1[] = {
                "settlement", gregoriancalendar, "maturity", gregoriancalendar1
            };
            Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.After", aobj1);
        }
        double d2 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar2, gregoriancalendar);
        double d3 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar2, gregoriancalendar1);
        double d4 = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        double d5 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        double d6 = (d2 / d5) * d;
        double d7 = 0.01D * d1 + d6;
        double d8 = (1.0D + (d3 * d) / d5) - d7;
        return (d8 / d7) * (d5 / d4);
    }

    public static double yearfrac(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1, DayCountBasis daycountbasis)
    {
        double d = daycountbasis.getMonthBasis().daysBetween(gregoriancalendar, gregoriancalendar1);
        double d1 = daycountbasis.getYearBasis().getDaysInYear(gregoriancalendar, gregoriancalendar1);
        return d / d1;
    }

    private static int monthsFromFrequency(int i)
    {
        Object aobj[];
        switch(i)
        {
        case 1: // '\001'
        case 2: // '\002'
        case 4: // '\004'
            return 12 / i;

        case 3: // '\003'
        default:
            aobj = (new Object[] {
                new Integer(i)
            });
            break;
        }
        Messages.throwIllegalArgumentException("com.imsl.finance", "Bond.Frequency", aobj);
        return 0;
    }

    private static GregorianCalendar first(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1)
    {
        return gregoriancalendar1.before(gregoriancalendar) ? gregoriancalendar1 : gregoriancalendar;
    }

    private static GregorianCalendar last(GregorianCalendar gregoriancalendar, GregorianCalendar gregoriancalendar1)
    {
        return gregoriancalendar1.after(gregoriancalendar) ? gregoriancalendar1 : gregoriancalendar;
    }

}
